<template>
  <div>
    <component
      v-if="currentComponent"
      style="width: 100%"
      clearable
      startPlaceholder="开始日期"
      endPlaceholder="结束日期"
      v-bind="{
        ...currentComponent,
        ...data,
        ...$props[currentComponent.config],
      }"
      v-model="formParam[data.key || data.prop]"
      :is="currentComponent.component"
      :placeholder="
        data.p || data.placeholder || `${rulesMessage[data.type]}${data.label}`
      "
      :data="findConfig(data.option, optionConfig)"
      :options="findConfig(data.option, optionConfig)"
      :filter-node-method="
        (value, data) => filterNodeMethod(value, data, data.searchKey)
      "
      :disabled="isDisabled(data.row)"
      @change="(value) => onChangeValue(value, $props[currentComponent.config])"
    >
      <template v-if="currentComponent.type === 'select'">
        <el-option
          v-for="v in findConfig(data.option, optionConfig)"
          :key="handleOption(v, 'label')"
          :label="handleOption(v, 'label')"
          :value="handleOption(v, 'value')"
        >
        </el-option>
      </template>
    </component>
  </div>
</template>

<script>
import {
  config,
  propsConfig,
  rulesMessage,
  fieldNames,
  findConfig,
} from "./index";

export default {
  data() {
    return {
      config,
      rulesMessage,
      findConfig,
    };
  },
  emits: ["changeValue"],
  props: {
    data: { type: Object, required: true, default: () => ({}) },
    ...propsConfig,
  },
  computed: {
    currentComponent() {
      return this.config.find((item) => item.type === this.data.type);
    },
  },
  methods: {
    // 选择器搜索
    filterNodeMethod(value, data, searchKey = "label") {
      return data[searchKey].includes(value);
    },
    // 表单禁用
    // row：表格当前行数据，data：当前组件数据，form表单不包含record
    isDisabled(row = null) {
      const { data, disabledConfig } = this.$props;
      const target = row || data;
      if (typeof data.disabled === "function") {
        return data.disabled({ row: target });
      }
      if (typeof data.disabled === "string") {
        // disabledKeys和disabled都存在时，进行对比相同则禁用
        if (target[data.disabledKeys] && disabledConfig[data.disabled]) {
          return !(target[data.disabledKeys] == disabledConfig[data.disabled]);
        }
        // 优先从 disabledConfig 获取外部控制状态
        if (disabledConfig && disabledConfig.hasOwnProperty(data.disabled)) {
          if (typeof disabledConfig[data.disabled] === "boolean") {
            return disabledConfig[data.disabled];
          }
          // 为字符串返回false，防止报错只接受布尔值
          return false;
        }
        // 字段级联动禁用规则：通过 record 的 key 匹配值是否相等并取反
        // 不相等则禁用，相等则打开，根据需求自行调整
        return !(target[data.disabledKeys] == target[data.disabled]);
      }
      // 直接返回静态禁用状态（Boolean），!!用于确保返回布尔值
      return !!data.disabled;
    },
    // 书写报错：处理 fieldNames 返回选项
    handleOption(v, key = "label") {
      if (this.data?.fieldNames) {
        return v[this.data?.fieldNames[key]];
      }
      if (v[fieldNames[key]]) {
        return v[fieldNames[key]];
      }
    },
    // 选择器选项返回选中数据
    getSelectedOption(selectData) {
      const { data, optionConfig } = this.$props;
      const { value, children } = data?.fieldNames || fieldNames;
      const options = findConfig(data.option, optionConfig);
      if (!options) return null;
      // 根据选中的 value 获取对应的完整数据项（id, name 等）
      const findOption = (options, val) => {
        for (let option of options) {
          if (option[value] === val) {
            return option;
          }
          if (option[children]) {
            const result = findOption(option[children], val);
            if (result) return result;
          }
        }
        return null;
      };
      return findOption(options, selectData);
    },
    // 输入框/选择器事件
    onChangeValue(value, configs = {}) {
      const { data, formParam } = this.$props;
      /**
       * el不支持当前选中返回所有数据，只返回value（id）
       * 对选择器进行筛选，返回完整数据项（id, name 等）
       */
      const id = Array.isArray(value) ? value[value?.length - 1] : value;
      const option = this.getSelectedOption(id);
      // 简单的处理
      if (data?.change) {
        return data.change(formParam, { value, option });
      }
      // 如果 args 对象 存在，根据 key:'value' 进行赋值操作
      const args = data?.param || data?.params;
      // 日期类型，返回数组，需要单独处理
      const dateType = ["daterange", "datetimerange", "monthrange"];
      if (args) {
        if (dateType.includes(data.type)) {
          for (const [index, item] of args.entries()) {
            formParam[item] = value?.[index];
          }
          return;
        }
        for (const key in args) {
          formParam[key] = option?.[args[key]];
        }
        return; // 可选
      }
      // 返回默认参数
      const { onChange } = configs;
      const datas = { ...data, value, option };
      const currentValue = configs[datas.key || datas.prop];
      /**
       * onChange：不根据字段，全部返回
       * currentValue：根据字段返回，只做当前处理
       */
      const events = currentValue || onChange;
      if (events) {
        return events(datas);
      }
      // 传递给父组件
      this.$emit("changeValue", datas);
    },
  },
};
</script>


<style  scoped lang="scss">
// 日期区间选择器溢出问题
:deep(.el-range__icon) {
  padding-left: 10px;
}
:deep(.el-range__close-icon) {
  padding-right: 10px;
}
</style>
